package com.africanmoviesmobile.ui;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Vector;

import org.pixmob.httpclient.HttpClientException;

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.AdapterView;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;

import com.africanmoviesmobile.R;
import com.africanmoviesmobile.webservice.AmmWebService;
import com.africanmoviesmobile.webservice.BasicAsyncCallback;
import com.africanmoviesmobile.webservice.WebServiceException;
import com.africanmoviesmobile.webservice.inf.Request;
import com.africanmoviesmobile.webservice.inf.User;
import com.africanmoviesmobile.webservice.inf.WebserviceObject;

public class RequestsActivity extends BaseActivity implements OnItemClickListener, OnScrollListener {

	private LayoutInflater mLayoutInflater;
	private ListView mRequestsListView;
	private LinearLayout mLoadingProgress;
	private LinearLayout mEmptyRequests;
		
	AmmWebService mAmmWebService;
	User mUser = null;
	
	private RequestsAdapter mRequestsAdapter;
	
	private boolean mLastItemVisible = false;
    private boolean mLoadingInProgress = false;
	private int mResultPage;
	private int mPageCount;
	
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		setContentView(R.layout.requests_activity);
		
		mRequestsAdapter = new RequestsAdapter();
		
		mLayoutInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		mLoadingProgress = (LinearLayout) mLayoutInflater.inflate(R.layout.loading_progress_small, null);
    	
		mEmptyRequests = (LinearLayout) findViewById(R.id.empty_requests);
		
		mRequestsListView = (ListView) findViewById(R.id.list);
		mRequestsListView.setDividerHeight(0);
		mRequestsListView.addHeaderView(mLoadingProgress);
		mRequestsListView.setAdapter(mRequestsAdapter);
		mRequestsListView.setOnItemClickListener(this);
		mRequestsListView.setOnScrollListener(this);
		
		Button requestMovie = (Button) findViewById(R.id.request_movie);
		requestMovie.setOnClickListener(new OnClickListener() {
			public void onClick(View view) {
				startActivity(new Intent(RequestsActivity.this, RequestMovieActivity.class));
			}
		});
		
		registerForContextMenu(mRequestsListView);
		
		mResultPage = 1;
		mAmmWebService = AmmWebService.getInstance(this);
		
		mAmmWebService.getUser(getLoginEmail(), new BasicAsyncCallback() {

			public void onComplete(final WebserviceObject[] result, final Object state) {

				User user = (User) result[0];
				
				if(user != null){
					
					mUser = user;
					
					Hashtable<String, String> params = new Hashtable<String, String>();
					params.put("page", Integer.toString(mResultPage));
					
					Request[] userRequests = null;
					
					try {
						userRequests = mUser.getRequests(params);
					} catch (HttpClientException e) {
						Log.w("AMM HttpClientException:", e.getMessage());
					} catch (IOException e) {
						Log.w("AMM IOException:", e.getMessage());
					} catch (WebServiceException e) {
						Log.w("AMM WebServiceException:", e.getMessage());
						toastMessage(e.getMessage());
					}
					
					if ((userRequests != null) && (userRequests.length > 0)) {
		
						mPageCount = mUser.getResultPageCount();
						
						runOnUiThread(new Runnable() {public void run() { mRequestsListView.removeHeaderView(mLoadingProgress); }});
						
						for (int i = 0; i < userRequests.length; i++) {
							final Request request = (Request) userRequests[i];
							runOnUiThread(new Runnable() {public void run() { mRequestsAdapter.add(request); }});	
						}
						
					}else{
						runOnUiThread(new Runnable() {
							public void run() {
								mRequestsListView.removeHeaderView(mLoadingProgress);
								mEmptyRequests.setVisibility(View.VISIBLE);
							}
						});
					}	
				}
			}

			public void onHttpClientException(final HttpClientException e, final Object state) {
				Log.w("AMM HttpClientException:", e.getMessage());
			}
			
			public void onIOException(final IOException e, final Object state) {
				Log.w("AMM IOException:", e.getMessage());
			}

			public void onWebServiceException(final WebServiceException e, final Object state) {
				Log.w("AMM WebServiceException:", e.getMessage());
				toastMessage(R.string.user_info_error);
			}

		}, null);
		
	}
	
	@Override
	public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
		Request request = (Request) mRequestsListView.getItemAtPosition(position);
		if((request != null) && (request.isAvailable())){
			final Intent intent = new Intent(this, MovieDetailActivity.class);
			intent.putExtra(MovieDetailActivity.EXTRA_MOVIE_ID, (int) request.getMovieId());
            startActivity(intent);
		}
	}
    
    @Override
	public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
		mLastItemVisible = (totalItemCount > 0) && (firstVisibleItem + visibleItemCount >= totalItemCount - 1);
	}
    
    @Override
	public void onScrollStateChanged(AbsListView view, int scrollState) {
		/**
		 * Check that the scrolling has stopped, and that the last item is
		 * visible.
		 */
		if ((scrollState == OnScrollListener.SCROLL_STATE_IDLE) && mLastItemVisible) {

			//check if we still have more page left and we aren't loading any data
			if ((mResultPage < mPageCount) && (!mLoadingInProgress)) {
				mRequestsListView.addFooterView(mLoadingProgress);
				mResultPage++;
				loadMoreRequests();
				mLastItemVisible = false;
				mLoadingInProgress = true;
			}
			
		}
	}

    @Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
        super.onCreateContextMenu(menu, v, menuInfo);
        menu.add(Menu.NONE, R.id.context_menu_remove_request, Menu.NONE, R.string.remove_from_requests);
    }
    
    @Override
    public boolean onContextItemSelected(MenuItem item) {
		 AdapterContextMenuInfo contextMenuInfo = (AdapterContextMenuInfo) item.getMenuInfo();
        switch (item.getItemId()) { 
            case R.id.context_menu_remove_request:
            	mRequestsAdapter.delete(contextMenuInfo.position);
                return true;       
        }
        return super.onContextItemSelected(item);
    }
	
    private void loadMoreRequests() {
        
    	Hashtable<String, String> params = new Hashtable<String, String>();
		params.put("page", Integer.toString(mResultPage));

		mUser.getRequests(params, new BasicAsyncCallback() {

			public void onComplete(final WebserviceObject[] result, final Object state) {
	
				runOnUiThread(new Runnable() {public void run() { mRequestsListView.removeFooterView(mLoadingProgress); }});
				
				mLoadingInProgress = false;
				
				Request[] userRequests = (Request[]) result;
	
				if ((userRequests != null)) {
																		
					for (int i = 0; i < userRequests.length; i++) {
						
						final Request request = (Request) (userRequests[i]);
						
						runOnUiThread(new Runnable() {public void run() { mRequestsAdapter.add(request); }});
						
					}
				} 
			}
	
			public void onHttpClientException(final HttpClientException e, final Object state) {
				mLoadingInProgress = false;
				runOnUiThread(new Runnable() {public void run() { mRequestsListView.removeFooterView(mLoadingProgress); }});
				Log.w("AMM HttpClientException:", e.getMessage());
			}
			
			public void onIOException(final IOException e, final Object state) {
				mLoadingInProgress = false;
				runOnUiThread(new Runnable() {public void run() { mRequestsListView.removeFooterView(mLoadingProgress); }});
				Log.w("AMM IOException:", e.getMessage());
			}
	
			public void onWebServiceException(final WebServiceException e, final Object state) {
				mLoadingInProgress = false;
				runOnUiThread(new Runnable() {public void run() { mRequestsListView.removeFooterView(mLoadingProgress); }});
				Log.w("AMM WebServiceException:", e.getMessage());
				toastMessage(e.getMessage());
			}

	}, null);
    	
    }
    
	public class RequestsAdapter extends BaseAdapter {

		private static final int VIEW_TYPE_LIST_REQUEST = 0;
		private static final int VIEW_TYPE_DELETING_REQUEST = 1;
		
		private Vector<Request> mListElements = new Vector<Request>();
		private ArrayList<Integer> mDeleteInProgressList = new ArrayList<Integer>();
		
		private class ViewHolder {
			public TextView mMovieTitle;
			public TextView mCountryName;
    	    public TextView mReleaseYear;
    	    public TextView mRequestDate;
    	    public TextView mRequestStatus;
    	    public ImageView mArrowRight;
    	    public TextView mLoadingProgressText;
    	}
				
        public RequestsAdapter() {
        }

        public int getCount() {
        	if (mListElements.isEmpty()) {
    			return 0;
    		} else {
    			return mListElements.size();
    		}
        }

        public Object getItem(int position) {
        	Request request = (Request) mListElements.elementAt(position);
        	return request;
        }

        public long getItemId(int position) {
        	Request request = (Request) mListElements.elementAt(position);
    		return request.getRequestId();
        }
        
        public int getItemViewType(int position) {
        	if(mDeleteInProgressList.contains(Integer.valueOf(position))){
        		return VIEW_TYPE_DELETING_REQUEST;
        	}else{
        		return VIEW_TYPE_LIST_REQUEST;
        	}
        }

        public int getViewTypeCount() {
            return 2;
        }

        public View getView(int position, View convertView, ViewGroup parent) {

        	Request request = (Request) mListElements.elementAt(position);
        	        	
        	ViewHolder holder;
        	
        	View requestRow = convertView;
        	
        	if(requestRow == null){
        		
        		holder  = new ViewHolder();
        		
        		if(getItemViewType(position) == VIEW_TYPE_LIST_REQUEST){
        			requestRow = mLayoutInflater.inflate(R.layout.requests_listview_row, parent, false);
            		holder.mMovieTitle = (TextView) requestRow.findViewById(R.id.movie_title);
            		holder.mCountryName = (TextView) requestRow.findViewById(R.id.country_name);
            		holder.mReleaseYear = (TextView) requestRow.findViewById(R.id.release_year);
            		holder.mRequestDate = (TextView) requestRow.findViewById(R.id.request_date);
            		holder.mRequestStatus = (TextView) requestRow.findViewById(R.id.request_status);
            		holder.mArrowRight = (ImageView) requestRow.findViewById(R.id.arrow_right);
        		}else{
        			requestRow = mLayoutInflater.inflate(R.layout.loading_progress_small, parent, false);
            		holder.mLoadingProgressText = (TextView) requestRow.findViewById(R.id.loading_progress_text);
            		holder.mLoadingProgressText.setText(R.string.removing_title);
        		}
        		
        		requestRow.setTag(holder);
        	}else{
        		holder = (ViewHolder) requestRow.getTag();
        	}
        	
        	if(getItemViewType(position) == VIEW_TYPE_LIST_REQUEST){
        		holder.mMovieTitle.setText(request.getMovieTitle());
            	holder.mCountryName.setText(request.getCountryName());
            	holder.mReleaseYear.setText(Integer.toString(request.getReleaseYear()));
            	holder.mRequestDate.setText(request.getDateRequested());
            	if(request.isAvailable()){
            		holder.mRequestStatus.setText(R.string.available);
            		holder.mArrowRight.setVisibility(View.VISIBLE);
            	}else{
            		holder.mRequestStatus.setText(R.string.not_yet_available);
            	}
        	}
     
        	return requestRow;
        }
   
        public void delete(final int position) {
        	
        	mDeleteInProgressList.add(Integer.valueOf(position));
        	notifyDataSetChanged();
        	
        	Request request = (Request) mListElements.elementAt(position);
        	
        	mUser.deleteRequest(request.getRequestId(), new BasicAsyncCallback() {

				public void onComplete(final boolean[] result, final Object state) {
												
					boolean response = (boolean) result[0];
										
					if (response == true) {
						
						runOnUiThread(new Runnable() {public void run() { 
							
							mDeleteInProgressList.remove(Integer.valueOf(position));
							mListElements.removeElementAt(position);
				            notifyDataSetChanged();

							toastMessage(R.string.request_removed_toast);
							
				            if(getCount() <= 0){
				            	mEmptyRequests.setVisibility(View.VISIBLE);
				            }
				            
						}});
						
					} else {
						runOnUiThread(new Runnable() {public void run() { 
							mDeleteInProgressList.remove(Integer.valueOf(position));
				            notifyDataSetChanged();
						}});
						toastMessage(R.string.request_removing_error_toast);
					}
					
				}
		
				public void onHttpClientException(final HttpClientException e, final Object state) {
					Log.w("AMM HttpClientException:", e.getMessage());
					runOnUiThread(new Runnable() {public void run() { 
						mDeleteInProgressList.remove(Integer.valueOf(position));
			            notifyDataSetChanged();
					}});
				}
				
				public void onIOException(final IOException e, final Object state) {
					Log.w("AMM IOException:", e.getMessage());
					runOnUiThread(new Runnable() {public void run() { 
						mDeleteInProgressList.remove(Integer.valueOf(position));
			            notifyDataSetChanged();
					}});
				}
		
				public void onWebServiceException(final WebServiceException e, final Object state) {
					Log.w("AMM WebServiceException:", e.getMessage());
					runOnUiThread(new Runnable() {public void run() { 
						mDeleteInProgressList.remove(Integer.valueOf(position));
			            notifyDataSetChanged();
					}});
					toastMessage(e.getMessage());
				}
		
			}, null);
        	
        }
        
        public void add(Request data) {
        	mListElements.addElement(data);
            notifyDataSetChanged();
        }

    }
}
